package educrypt.cryptanalysis.vigenere;

import java.util.ArrayList;
import java.util.List;

import educrypt.analysis.*;
import educrypt.commons.*;
import educrypt.cryptanalysis.FrequencyBasedCryptAnalysis;
import educrypt.database.dao.FrequencyAnalysisDAO;
import educrypt.exceptions.EduCryptException;

public class CryptAnalysisVigenere {
	private Text text;
	private Alphabet alphabet;

	public CryptAnalysisVigenere(Text cipherText, Alphabet alphabet) {
		this.text = cipherText;
		this.alphabet = alphabet;
	}

	public List<Integer> cryptAnalyze() throws EduCryptException {
		int keyLenght = KasiskiExamination.examine(this.text, this.alphabet);

		List<Text> splitText = splitText(keyLenght);
		List<Integer> offsets = new ArrayList<Integer>();

		FrequencyAnalysisDAO analysisDAO = FrequencyAnalysisDAO.getInstance();

		Frequencies averageFrequencies = analysisDAO.getAverageFrequencies(
				this.alphabet.getName(), 1, text.getLanguage(), text.getType());

		for (Text text : splitText) {
			FrequencyAnalysis analysisCipherText = new FrequencyAnalysis(text,
					this.alphabet, 1);
			Frequencies cipherTextFrequencies = analysisCipherText
					.getFrequencies();

			if (cipherTextFrequencies.getMaxNumberOfSamePercentageOcurrences() > 3) {
				throw new EduCryptException();
			}

			FrequencyBasedCryptAnalysis cryptoanalysis = new FrequencyBasedCryptAnalysis(
					cipherTextFrequencies, averageFrequencies);
			offsets.add(cryptoanalysis.getSortedOffsetsFromCaesarCandidateKeys(
					cryptoanalysis.cryptAnalyze()).get(0));
		}
		return offsets;
	}

	private List<Text> splitText(int columnsToSplit) {
		int textSize = this.text.size();
		List<StringBuffer> splitContent = new ArrayList<StringBuffer>(
				columnsToSplit);
		for (int i = 0; i < columnsToSplit; i++) {
			splitContent.add(new StringBuffer(textSize / columnsToSplit));
		}
		int j = 0;
		for (int i = 0; j < textSize; i++) {
			int pos = i % columnsToSplit;
			boolean isAlphabetSymbol;
			StringBuffer column = splitContent.get(pos);
			do {
				// char symbolToAdd = this.text.getContent().toCharArray()[j];
				char symbolToAdd = this.text.getContent().charAt(j);

				column.append(symbolToAdd);
				isAlphabetSymbol = this.alphabet.containsSymbol(symbolToAdd);
				j++;
			} while (!isAlphabetSymbol && j < this.text.size());
			// splitContent.set(pos, column);
		}
		List<Text> splitText = new ArrayList<Text>();
		for (StringBuffer content : splitContent) {
			Text text = new Text();
			text.setContent(content.toString());
			text.setLanguage(this.text.getLanguage());
			text.setType(this.text.getType());
			text.setName(this.text.getName());
			splitText.add(text);
		}
		return splitText;
	}
}
